package com.cnjson.sensor.protocolARP;


import com.cnjson.sensor.util.CRC16;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

@Component
public abstract class GeneralProtocolAbstract implements Protocol {
    public static final Logger logger = LoggerFactory.getLogger(GeneralProtocolAbstract.class);


    public void read(SocketChannel client, Selector selector, Map<String, SocketChannel> serverSocketMap,
                     Map<SocketChannel, AtomicBoolean> isWritingMap, Map<SocketChannel, AtomicBoolean> isReadingMap) {


        try {


            byte[] response = null;
            //校验数据是否正确，并将数据转化为byteBuffer
            String[] data = checkData(client);
            if (data == null) return;



            String remote = client.getRemoteAddress().toString();
            if (serverSocketMap == null || (serverSocketMap != null && !serverSocketMap.containsKey(remote))) {
                serverSocketMap.put(remote, client);
            }



            //处理数据
            response = handleData(client, data);





            if (response != null) {
                AtomicBoolean isWriting = isWritingMap.get(client);
                if (isWriting == null) {
                    isWriting = new AtomicBoolean(false);
                    isWritingMap.put(client, isWriting);
                }
                while (isWriting.get()) {
                    Thread.sleep(5);
                }
                isWriting.set(true);
                client.register(selector, SelectionKey.OP_WRITE, response);
            } else {
                logger.warn("-----------服务端没有可应答的数据！----------");
            }
        } catch (Exception e) {
            try {
                SelectionKey selectionKey = client.keyFor(selector);
                if (selectionKey != null) {
                    selectionKey.cancel();
                }
                String address = client.getRemoteAddress().toString();

                //模板模式
                doSomethingInReadingError(client);

                serverSocketMap.remove(address);

                logger.warn("客户端[" + client + "]关闭了连接,原因[" + e + "]");
                if (client != null) {
                    client.close();
                }
            } catch (Exception e1) {
                logger.error("客户端[" + client + "]关闭异常");// + e1.getMessage()
            }
        } finally {
            AtomicBoolean isReading = isReadingMap.get(client);
            isReading.set(false);
        }

    }

    public abstract byte[] handleData(SocketChannel client, String[] data);

    public abstract String[] checkData(SocketChannel client);

    public abstract void doSomethingInReadingError(SocketChannel client);


    public boolean checkCRCVal( ByteBuffer crcCheckData, String[] data) {

        String crc1 = data[data.length-4];
        String crc2 = data[data.length-3];

        String originCrc = crc1 + crc2;
        //注释掉原来的用replace的方法
        String crc = CRC16.getCRC(crcCheckData.array());

        logger.info("原数据CRC值=" + originCrc + ",计算CRC结果 :[" + crc + "]");
        if (crc.equalsIgnoreCase(originCrc)) {
            return true;
        }
        return false;
    }


}
